package com.gurun.gateway;

import android.content.Context;
import android.util.Log;

import com.google.gson.Gson;
import com.gurun.base.Logger;
import com.gurun.model.base.ResultObserver;
import com.gurun.model.base.RetrofitManager;
import com.gurun.model.bean.ApiResult;
import com.gurun.model.bean.gateway.ReportGatewayDataRequestBean;
import com.gurun.model.bean.gateway.ReportGatewayDataResultBean;
import com.gurun.model.bean.gateway.command.GateWayCommandModel;
import com.gurun.model.database.AppDatabase;
import com.gurun.model.database.entity.GateWayCommand;
import com.gurun.model.service.GateWayService;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import java.util.List;

import io.reactivex.Scheduler;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public interface GatewayContract {

    interface DataCallBack {

        void onComplete();

        void onLoading();

        void onLoaded(ReportGatewayDataResultBean datas);

        void onError(String msg);
    }

    interface DeviceJoinedCallBack {
        void onDeviceJoined(GateWayCommandModel gateWayCommandModel);
    }

    interface FullDataCallBack {
        void callBack(GateWayCommandModel gateWayCommandModel);
    }

    class GatewayPresenter {

        private Context mContext;

        public GatewayPresenter(Context context) {
            this.mContext = context;
        }

        /**
         * 上报数据到服务器
         *
         * @param data
         * @param callBack
         */
        public void reportDataToServer(String data, boolean needQueryDataFromDatabase, final DataCallBack callBack) {
            //TODO 记得将这个用rxjava改成一个方法流
//            if (needQueryDataFromDatabase) {
//                GateWayCommandModel gateWayCommandModel = CommandFactory.stringCommandToModel(data);
//                fullDataByShortId(gateWayCommandModel, new FullDataCallBack() {
//                    @Override
//                    public void callBack(GateWayCommandModel gateWayCommandModel) {
//                        if (gateWayCommandModel != null) {
//                            if (gateWayCommandModel.getCmd().contains("unknow_device")
//                                    || "unknown device".equals(gateWayCommandModel.getModel())
//                                    || "0".equals(gateWayCommandModel.getSid())
//                                    ) {
//                                return;
//                            }
//                            Gson gson = new Gson();
//                            String datas = gson.toJson(gateWayCommandModel);
//                            report(datas, callBack);
//                        }
//                    }
//                });
//            } else {
//                report(data, callBack);
//            }
            if (needQueryDataFromDatabase) {
                GateWayCommandModel gateWayCommandModel = CommandFactory.stringCommandToModel(data);
                if (gateWayCommandModel != null) {
                    if ("unknow".equals(gateWayCommandModel.getModel()) || "0".equals(gateWayCommandModel.getSid()) || gateWayCommandModel.getShort_id() == 0) {
                        fullDataByShortId(gateWayCommandModel, new FullDataCallBack() {
                            @Override
                            public void callBack(GateWayCommandModel gateWayCommandModel) {
                                if (gateWayCommandModel != null) {
                                    if (gateWayCommandModel.getCmd().contains("unknow_device")
                                            || "unknow".equals(gateWayCommandModel.getModel())
                                            || "0".equals(gateWayCommandModel.getSid())
                                            ) {
                                        return;
                                    }
                                    Gson gson = new Gson();
                                    String datas = gson.toJson(gateWayCommandModel);
                                    report(datas, callBack);
                                }
                            }
                        });
                    } else {
                        report(data, callBack);
                    }
                }
            } else {
                report(data, callBack);
            }
        }

        private void report(String data, final DataCallBack callBack) {
            ReportGatewayDataRequestBean requestBean = new ReportGatewayDataRequestBean();
            requestBean.setData(data);
            requestBean.setToken("token");
            requestBean.setUserId(123456);
            requestBean.setVersion("1.0");

            RetrofitManager.getInstance().createApiService(GateWayService.class)
                    .reportGatewayData(requestBean)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe((new ResultObserver<ReportGatewayDataResultBean>() {

                        @Override
                        public void onLoading(Disposable d) {
                            if (callBack != null) {
                                callBack.onLoading();
                            }
                        }

                        @Override
                        public void onOtherError(Throwable e) {
                            if (callBack != null) {
                                callBack.onError("与服务器连接失败");
                            }
                        }

                        @Override
                        public void onLoaded() {
                            if (callBack != null) {
                                callBack.onComplete();
                            }
                        }

                        @Override
                        public void onSuccess(ReportGatewayDataResultBean result, String msg) {
                            if (callBack != null) {
                                callBack.onLoaded(result);
                            }
                        }

                        @Override
                        public void onApiError(ApiResult result) {
                            if (callBack != null) {
                                if (result != null) {
                                    callBack.onError(result.getRetMsg());
                                } else {
                                    callBack.onError("与服务器连接失败");
                                }
                            }
                        }
                    }));
        }

        //update命令的时候拿到sid去查询出来记录，如果存在，就将short_id更新
        //remove 命令的时候先拿sid查是否存在记录，存在就删除
        // join的时候先判断有没有这个记录(也许多个)，有的话把全部删除，然后插入新的
        //上报数据的时候拿short_id去查询数据，然后封装好再上报到服务器

        public void updateShortId(final GateWayCommandModel gateWayCommandModel) {
            if (gateWayCommandModel != null) {
                AppDatabase.getInstance(mContext).GateWayDao().queryBySid(gateWayCommandModel.getSid())
                        .map(new Function<List<GateWayCommand>, List<GateWayCommand>>() {
                            @Override
                            public List<GateWayCommand> apply(List<GateWayCommand> gateWayCommands) throws Exception {
                                if (gateWayCommands != null) {
                                    for (GateWayCommand item : gateWayCommands) {
                                        item.setShort_id(gateWayCommandModel.getShort_id());
                                        AppDatabase.getInstance(mContext).GateWayDao().update(item);
                                    }
                                }
                                return gateWayCommands;
                            }
                        })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new SingleObserver<List<GateWayCommand>>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onSuccess(List<GateWayCommand> gateWayCommands) {
                            }

                            @Override
                            public void onError(Throwable e) {

                            }
                        });
            }
        }

        public void removeBySid(GateWayCommandModel gateWayCommandModel) {
            if (gateWayCommandModel != null) {
                AppDatabase.getInstance(mContext).GateWayDao().queryBySid(gateWayCommandModel.getSid())
                        .map(new Function<List<GateWayCommand>, List<GateWayCommand>>() {
                            @Override
                            public List<GateWayCommand> apply(List<GateWayCommand> gateWayCommands) throws Exception {
                                if (gateWayCommands != null) {
                                    for (GateWayCommand item : gateWayCommands) {
                                        AppDatabase.getInstance(mContext).GateWayDao().delete(item);
                                    }
                                }
                                return gateWayCommands;
                            }
                        })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new SingleObserver<List<GateWayCommand>>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onSuccess(List<GateWayCommand> gateWayCommands) {
                            }

                            @Override
                            public void onError(Throwable e) {

                            }
                        });
            }
        }

        public void deviceJoin(final GateWayCommandModel gateWayCommandModel, final DeviceJoinedCallBack callBack) {
            if (gateWayCommandModel != null) {
                AppDatabase.getInstance(mContext).GateWayDao().queryBySid(gateWayCommandModel.getSid())
                        .map(new Function<List<GateWayCommand>, List<GateWayCommand>>() {
                            @Override
                            public List<GateWayCommand> apply(List<GateWayCommand> gateWayCommands) throws Exception {
                                if (gateWayCommands != null) {
                                    for (GateWayCommand item : gateWayCommands) {
                                        AppDatabase.getInstance(mContext).GateWayDao().delete(item);
                                    }
                                }
                                GateWayCommand gateWay = new GateWayCommand();
                                gateWay.setShort_id(gateWayCommandModel.getShort_id());
                                gateWay.setCmd(gateWayCommandModel.getCmd());
                                gateWay.setData(gateWayCommandModel.getData());
                                gateWay.setModel(gateWayCommandModel.getModel());
                                gateWay.setSid(gateWayCommandModel.getSid());
                                gateWay.setToken(gateWayCommandModel.getToken());
                                long result = AppDatabase.getInstance(mContext).GateWayDao().insert(gateWay);
                                Logger.d("deviceJoin----insert result----" + result);
                                return gateWayCommands;
                            }
                        })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new SingleObserver<List<GateWayCommand>>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onSuccess(List<GateWayCommand> gateWayCommands) {
                                if (callBack != null) {
                                    callBack.onDeviceJoined(gateWayCommandModel);
                                }
                            }

                            @Override
                            public void onError(Throwable e) {

                            }
                        });
            }
        }

        public void fullDataByShortId(final GateWayCommandModel gateWayCommandModel, final FullDataCallBack callBack) {
            if (gateWayCommandModel != null) {
                AppDatabase.getInstance(mContext).GateWayDao().queryByShortId(gateWayCommandModel.getShort_id())
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new SingleObserver<List<GateWayCommand>>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onSuccess(List<GateWayCommand> gateWayCommands) {
                                if (gateWayCommands != null && gateWayCommands.size() > 0) {
                                    GateWayCommand gateWay = gateWayCommands.get(0);
                                    if (gateWay != null) {
                                        gateWayCommandModel.setSid(gateWay.getSid());
                                        gateWayCommandModel.setModel(gateWay.getModel());//unknown device
                                        if (gateWayCommandModel.getCmd().contains("unknow_device")) {
                                            if ("heartbeat_unknow_device".equals(gateWayCommandModel.getCmd())) {
                                                gateWayCommandModel.setCmd("heartbeat");
                                            } else {
                                                gateWayCommandModel.setCmd("report");
                                            }
                                        }
                                    }
                                }
                                if (callBack != null) {
                                    callBack.callBack(gateWayCommandModel);
                                }
                            }

                            @Override
                            public void onError(Throwable e) {

                            }
                        });
            }
        }

    }
}
